﻿using System;
using System.Collections.Generic;
using System.Timers;
using Commands;
using Commands.Logging;
using Commands.Scheduling;
using NHotkey.Wpf;
using RemoteCommands.ViewModels;
using System.Windows;
using System.ComponentModel;
using System.Windows.Input;
using Hardcodet.Wpf.TaskbarNotification;

namespace RemoteCommands
{
    class MagicAttribute : Attribute { }
    class NoMagicAttribute : Attribute { }

    [Magic]
    internal class MainViewModel : ViewModelBase
    {
        public MainViewModel(Action<bool> showHide)
        {
            // Create executor.
            _executor = new Executor();
            _executor.TaskUpdated += new Action<Message>(_ExecutorTaskUpdated);

            RegisterCommand("Check", x => { _executor.GetAndExecute(); });
            RegisterCommand("Execute", x => { _executor.Execute(CommandString); });
            RegisterCommand("Suspend", x => { _executor.Suspend(); });
            RegisterCommand("Hide", x => showHide(true));
            RegisterCommand("ShowHide", x => showHide(false));
            RegisterCommand("Close", x => App.Current.Shutdown());

            // Init hiding.
            _ReadHideSettings(_executor.HiddeSettings);
            _InitHotkeys(_executor);

            var timer = new Timer(1000);
            timer.Elapsed += (_, __) => _UpdateTimes();
            timer.Start();
            _UpdateTimes();
        }

        #region Properties for bindings

        public string CommandString
        {
            get;
            set;
        }

        public string Result
        {
            get;
            private set;
        }

        public ISchedule Schedule
        {
            get
            {
                return _executor.Schedule;
            }
        }

        public bool SuspendEnabled
        {
            get
            {
                return Schedule.SuspendEnabled;
            }
            set
            {
                Schedule.SuspendEnabled = value;
            }
        }

        public bool AutoCheckEnabled
        {
            get
            {
                return Schedule.AutoCheckEnabled;
            }
            set
            {
                Schedule.AutoCheckEnabled = value;
            }
        }

        public string SuspendTime
        {
            get;
            private set;
        }

        // TODO. replace with converter
        public Visibility Suspend
        {
            get
            {
                return string.IsNullOrEmpty(SuspendTime) ? Visibility.Collapsed : Visibility.Visible;
            }
        }

        public string WakeUpTime { get; set; }

        public string CheckTime { get; set; }

        #endregion

        #region Private members

        private void _ReadHideSettings(Commands.Settings.HiddeSettings hideSettings)
        {
            if(hideSettings.DontShowTrayIcon)
                App.TrayIcon.Visibility = Visibility.Collapsed;

            if(hideSettings.StartMinimized)
                Commands["Hide"].Execute(null);
        }

        private void _InitHotkeys(Executor _executor)
        {
            try
            {
                HotkeyManager.Current.AddOrReplace("Invisible", Key.Subtract, ModifierKeys.Control | ModifierKeys.Alt, OnInvisible);
                HotkeyManager.Current.AddOrReplace("Hide", Key.Add, ModifierKeys.Control | ModifierKeys.Alt, OnHide);
            }
            catch (Exception ex)
            { }
        }

        private void OnHide(object sender, NHotkey.HotkeyEventArgs e)
        {
            Commands["ShowHide"].Execute(null);
        }
        private void OnInvisible(object sender, NHotkey.HotkeyEventArgs e)
        {
            Commands["ShowHide"].Execute(null);

            App.TrayIcon.Visibility = App.Current.MainWindow.Visibility;
        }

        private void _ExecutorTaskUpdated(Message task)
        {
            LogFile.AddString(task.Text);
        }

        private void _UpdateTimes()
        {
            if (_executor.Schedule == null)
                return;

            if (_executor.Schedule.SuspendTime != DateTime.MinValue && SuspendEnabled)
            {
                SuspendTime = _ConvertTimeToText(_executor.Schedule.SuspendTime);
                WakeUpTime = _executor.Schedule.GetWakeupTime(_executor.Schedule.NextCheckTime).ToString(TIMESPAN_FORMAT);
            }
            else
            {
                SuspendTime = null;
                WakeUpTime = null;
            }

            if (_executor.Schedule.NextCheckTime != DateTime.MinValue && AutoCheckEnabled)
            {
                CheckTime = _ConvertTimeToText(_executor.Schedule.NextCheckTime);
            }

            OnPropertyChanged(() => WakeUpTime);
            OnPropertyChanged(() => SuspendTime);
            OnPropertyChanged(() => CheckTime);
            OnPropertyChanged(() => Suspend);
        }

        private string _ConvertTimeToText(DateTime time)
        {
            return (time - DateTime.Now).ToString(TIMESPAN_FORMAT);
        }

        private const string TIMESPAN_FORMAT = @"hh\:mm\:ss";

        private readonly Executor _executor;

        #endregion
    }
}
